// utils/track.js
function send(data) {
  const img = new Image();
  img.src = `/track.gif?data=${encodeURIComponent(JSON.stringify(data))}`;
}

export function trackEvent(event, extra = {}) {
  const data = {
    event,
    page: window.location.pathname,
    userId: localStorage.getItem("userId") || "guest",
    timestamp: Date.now(),
    extra
  };
  send(data);
}

/**
 * 首屏加载上报
 * @param {number} threshold 超过多少 ms 才上报（可选，不传则每次都上报）
 * 使用示例：
 *    main.js中
 *    import {trackFirstScreen} from "@/utils/track.js"
 *    trackFirstScreen(3000);
 */
export function trackFirstScreen(threshold) {
  if (!performance.getEntriesByType) return;

  const [nav] = performance.getEntriesByType("navigation");
  if (!nav) return;

  const duration = nav.loadEventEnd - nav.startTime; // 总加载耗时
  const fp = performance.getEntriesByType("paint").find(e => e.name === "first-paint");
  const firstPaint = fp ? fp.startTime : null;

  // 判断是否首页
  const isHome = window.location.pathname === "/";

  if (isHome) {
    if (!threshold || duration > threshold) {
      trackEvent("first_screen_load", {
        duration,
        firstPaint
      });
    }
  }
}


/**
 * Vue 自定义指令：v-track-click
 * 用于按钮点击上报
 * - 自动提取按钮文本
 * - 如果开发者传值，则优先使用
 * 使用示例：
 *   <button v-track-click>自动提取</button>
 *   <button v-track-click="'提交按钮'">会用绑定值</button>
 */
export const vTrackClick = {
  mounted(el, binding) {
    const getText = () => {
      if (binding.value && typeof binding.value === "string") {
        return binding.value.trim();
      }
      return (el.innerText || el.value || "unknown").trim();
    };

    el.__trackClickHandler__ = () => {
      trackEvent("button_click", { buttonText: getText() });
    };

    el.addEventListener("click", el.__trackClickHandler__);
  },
  unmounted(el) {
    el.removeEventListener("click", el.__trackClickHandler__);
  }
};

/**
 * Vue 自定义指令：v-track-expose
 * 当元素进入视口时上报
 * 使用方式：
 *   <div v-track-expose="'广告Banner'"></div>
 */
export const vTrackExpose = {
  mounted(el, binding) {
    const exposeText = binding.value || el.innerText || "unknown";

    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          trackEvent("element_expose", { elementText: exposeText });
          // 曝光上报一次后停止观察
          observer.unobserve(el);
        }
      });
    });

    observer.observe(el);
    el.__trackExposeObserver__ = observer;
  },
  unmounted(el) {
    if (el.__trackExposeObserver__) {
      el.__trackExposeObserver__.disconnect();
    }
  }
};


/**
 * 页面进入埋点
 * @param {string} path 当前页面路径
 * 使用方式：
 *    router.afterEach((to,form) => trackPageView(to.fullPath))
 */
export function trackPageView(path) {
  // 判断是否刷新
  const isReload = performance.navigation.type === 1;
  trackEvent("page_view", { page: path, isReload });
}

/**
 * 页面报错 
 */
export function initPageErrorTracking() {
  // JS 报错
  window.onerror = (message, source, lineno, colno, error) => {
    trackEvent("page_error", {
      message,
      source,
      lineno,
      colno,
      stack: error?.stack || ""
    });
  };

  // Promise 未捕获异常
  window.onunhandledrejection = (event) => {
    let reason = event.reason;
    let message = "";
    let stack = "";
    if (reason instanceof Error) {
      message = reason.message;
      stack = reason.stack;
    } else if (typeof reason === "string") {
      message = reason;
    } else {
      message = JSON.stringify(reason);
    }
    trackEvent("page_error", { message, stack });
  };
}

/**
 * 接口报错 & 接口耗时
 * @param {object} axiosInstance axios实例
 * @param {number} threshold 接口耗时超过threshold时上报
 * 使用示例：
 *    在require.js中创建axios实例，在main.js中引入axios实例并调用setupAxiosTracking方法
 *    import service from "@/require.js";
 *    import { setupAxiosTracking } from "@/utils/track";
 *    setupAxiosTracking(service, 1000); // 阈值 1000ms
 */
export function setupAxiosTracking(axiosInstance, threshold = 1000) {
  axiosInstance.interceptors.request.use(config => {
    config.metadata = { startTime: new Date().getTime() };
    return config;
  });

  axiosInstance.interceptors.response.use(
    response => {
      const duration = new Date().getTime() - response.config.metadata.startTime;
      if (duration > threshold) {
        trackEvent("api_slow", {
          url: response.config.url,
          method: response.config.method.toUpperCase(),
          params: response.config.data || response.config.params || {},
          duration
        });
      }
      return response;
    },
    error => {
      const config = error.config || {};
      const duration = new Date().getTime() - (config.metadata?.startTime || 0);
      trackEvent("api_error", {
        url: config.url || "unknown",
        method: config.method?.toUpperCase() || "unknown",
        params: config.data || config.params || {},
        status: error.response?.status || "network_error",
        response: error.response?.data || error.message || "",
        duration
      });
      return Promise.reject(error);
    }
  );
}


